{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Predicting Remaining Useful Life\n",
    "<p style=\"margin:30px\">\n",
    "    <img style=\"display:inline; margin-right:50px\" width=50% src=\"https://www.featuretools.com/wp-content/uploads/2017/12/FeatureLabs-Logo-Tangerine-800.png\" alt=\"Featuretools\" />\n",
    "    <img style=\"display:inline\" width=15% src=\"https://upload.wikimedia.org/wikipedia/commons/e/e5/NASA_logo.svg\" alt=\"NASA\" />\n",
    "</p>\n",
    "\n",
    "The general setup for the problem is a common one: we have a single table of sensor observations over time. Now that collecting information is easier than ever, most industries have already generated *time-series* type problems by the way that they store data. As such, it is crucial to be able to handle data in this form. Thankfully, built-in functionality from [Featuretools](https://www.featuretools.com) handles time varying data well. \n",
    "\n",
    "We'll demonstrate an end-to-end workflow using a [Turbofan Engine Degradation Simulation Data Set](https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository/#turbofan) from NASA. This notebook demonstrates a rapid way to predict the Remaining Useful Life (RUL) of an engine using an initial dataframe of time-series data. There are three sections of the notebook:\n",
    "1. [Understand the Data](#Step-1:-Understanding-the-Data)\n",
    "2. [Generate features](#Step-2:-DFS-and-Creating-a-Model)\n",
    "3. [Make predictions with Machine Learning](#Step-3:-Using-the-Model)\n",
    "\n",
    "*To run the notebooks, you need to download the data yourself. Download and unzip the file from[https://ti.arc.nasa.gov/c/13/](https://ti.arc.nasa.gov/c/6/) and place the files in the 'data' directory*\n",
    "\n",
    "\n",
    "## Highlights\n",
    "* Quickly make end-to-end workflow using time-series data\n",
    "* Find interesting automatically generated features\n",
    "\n",
    "# Step 1: Understanding the Data\n",
    "Here we load in the train data and give the columns names according to the `description.txt` file. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded data with:\n",
      "61249 Recordings\n",
      "249 Engines\n",
      "21 Sensor Measurements\n",
      "3 Operational Settings\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>engine_no</th>\n",
       "      <th>time_in_cycles</th>\n",
       "      <th>operational_setting_1</th>\n",
       "      <th>operational_setting_2</th>\n",
       "      <th>operational_setting_3</th>\n",
       "      <th>sensor_measurement_1</th>\n",
       "      <th>sensor_measurement_2</th>\n",
       "      <th>sensor_measurement_3</th>\n",
       "      <th>sensor_measurement_4</th>\n",
       "      <th>sensor_measurement_5</th>\n",
       "      <th>...</th>\n",
       "      <th>sensor_measurement_14</th>\n",
       "      <th>sensor_measurement_15</th>\n",
       "      <th>sensor_measurement_16</th>\n",
       "      <th>sensor_measurement_17</th>\n",
       "      <th>sensor_measurement_18</th>\n",
       "      <th>sensor_measurement_19</th>\n",
       "      <th>sensor_measurement_20</th>\n",
       "      <th>sensor_measurement_21</th>\n",
       "      <th>index</th>\n",
       "      <th>time</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>index</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>42.0049</td>\n",
       "      <td>0.8400</td>\n",
       "      <td>100.0</td>\n",
       "      <td>445.00</td>\n",
       "      <td>549.68</td>\n",
       "      <td>1343.43</td>\n",
       "      <td>1112.93</td>\n",
       "      <td>3.91</td>\n",
       "      <td>...</td>\n",
       "      <td>8074.83</td>\n",
       "      <td>9.3335</td>\n",
       "      <td>0.02</td>\n",
       "      <td>330</td>\n",
       "      <td>2212</td>\n",
       "      <td>100.00</td>\n",
       "      <td>10.62</td>\n",
       "      <td>6.3670</td>\n",
       "      <td>0</td>\n",
       "      <td>2000-01-01 00:00:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>20.0020</td>\n",
       "      <td>0.7002</td>\n",
       "      <td>100.0</td>\n",
       "      <td>491.19</td>\n",
       "      <td>606.07</td>\n",
       "      <td>1477.61</td>\n",
       "      <td>1237.50</td>\n",
       "      <td>9.35</td>\n",
       "      <td>...</td>\n",
       "      <td>8046.13</td>\n",
       "      <td>9.1913</td>\n",
       "      <td>0.02</td>\n",
       "      <td>361</td>\n",
       "      <td>2324</td>\n",
       "      <td>100.00</td>\n",
       "      <td>24.37</td>\n",
       "      <td>14.6552</td>\n",
       "      <td>1</td>\n",
       "      <td>2000-01-01 00:10:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>42.0038</td>\n",
       "      <td>0.8409</td>\n",
       "      <td>100.0</td>\n",
       "      <td>445.00</td>\n",
       "      <td>548.95</td>\n",
       "      <td>1343.12</td>\n",
       "      <td>1117.05</td>\n",
       "      <td>3.91</td>\n",
       "      <td>...</td>\n",
       "      <td>8066.62</td>\n",
       "      <td>9.4007</td>\n",
       "      <td>0.02</td>\n",
       "      <td>329</td>\n",
       "      <td>2212</td>\n",
       "      <td>100.00</td>\n",
       "      <td>10.48</td>\n",
       "      <td>6.4213</td>\n",
       "      <td>2</td>\n",
       "      <td>2000-01-01 00:20:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1</td>\n",
       "      <td>4</td>\n",
       "      <td>42.0000</td>\n",
       "      <td>0.8400</td>\n",
       "      <td>100.0</td>\n",
       "      <td>445.00</td>\n",
       "      <td>548.70</td>\n",
       "      <td>1341.24</td>\n",
       "      <td>1118.03</td>\n",
       "      <td>3.91</td>\n",
       "      <td>...</td>\n",
       "      <td>8076.05</td>\n",
       "      <td>9.3369</td>\n",
       "      <td>0.02</td>\n",
       "      <td>328</td>\n",
       "      <td>2212</td>\n",
       "      <td>100.00</td>\n",
       "      <td>10.54</td>\n",
       "      <td>6.4176</td>\n",
       "      <td>3</td>\n",
       "      <td>2000-01-01 00:30:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>25.0063</td>\n",
       "      <td>0.6207</td>\n",
       "      <td>60.0</td>\n",
       "      <td>462.54</td>\n",
       "      <td>536.10</td>\n",
       "      <td>1255.23</td>\n",
       "      <td>1033.59</td>\n",
       "      <td>7.05</td>\n",
       "      <td>...</td>\n",
       "      <td>7865.80</td>\n",
       "      <td>10.8366</td>\n",
       "      <td>0.02</td>\n",
       "      <td>305</td>\n",
       "      <td>1915</td>\n",
       "      <td>84.93</td>\n",
       "      <td>14.03</td>\n",
       "      <td>8.6754</td>\n",
       "      <td>4</td>\n",
       "      <td>2000-01-01 00:40:00</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 28 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "       engine_no  time_in_cycles  operational_setting_1  \\\n",
       "index                                                     \n",
       "0              1               1                42.0049   \n",
       "1              1               2                20.0020   \n",
       "2              1               3                42.0038   \n",
       "3              1               4                42.0000   \n",
       "4              1               5                25.0063   \n",
       "\n",
       "       operational_setting_2  operational_setting_3  sensor_measurement_1  \\\n",
       "index                                                                       \n",
       "0                     0.8400                  100.0                445.00   \n",
       "1                     0.7002                  100.0                491.19   \n",
       "2                     0.8409                  100.0                445.00   \n",
       "3                     0.8400                  100.0                445.00   \n",
       "4                     0.6207                   60.0                462.54   \n",
       "\n",
       "       sensor_measurement_2  sensor_measurement_3  sensor_measurement_4  \\\n",
       "index                                                                     \n",
       "0                    549.68               1343.43               1112.93   \n",
       "1                    606.07               1477.61               1237.50   \n",
       "2                    548.95               1343.12               1117.05   \n",
       "3                    548.70               1341.24               1118.03   \n",
       "4                    536.10               1255.23               1033.59   \n",
       "\n",
       "       sensor_measurement_5         ...          sensor_measurement_14  \\\n",
       "index                               ...                                  \n",
       "0                      3.91         ...                        8074.83   \n",
       "1                      9.35         ...                        8046.13   \n",
       "2                      3.91         ...                        8066.62   \n",
       "3                      3.91         ...                        8076.05   \n",
       "4                      7.05         ...                        7865.80   \n",
       "\n",
       "       sensor_measurement_15  sensor_measurement_16  sensor_measurement_17  \\\n",
       "index                                                                        \n",
       "0                     9.3335                   0.02                    330   \n",
       "1                     9.1913                   0.02                    361   \n",
       "2                     9.4007                   0.02                    329   \n",
       "3                     9.3369                   0.02                    328   \n",
       "4                    10.8366                   0.02                    305   \n",
       "\n",
       "       sensor_measurement_18  sensor_measurement_19  sensor_measurement_20  \\\n",
       "index                                                                        \n",
       "0                       2212                 100.00                  10.62   \n",
       "1                       2324                 100.00                  24.37   \n",
       "2                       2212                 100.00                  10.48   \n",
       "3                       2212                 100.00                  10.54   \n",
       "4                       1915                  84.93                  14.03   \n",
       "\n",
       "       sensor_measurement_21  index                time  \n",
       "index                                                    \n",
       "0                     6.3670      0 2000-01-01 00:00:00  \n",
       "1                    14.6552      1 2000-01-01 00:10:00  \n",
       "2                     6.4213      2 2000-01-01 00:20:00  \n",
       "3                     6.4176      3 2000-01-01 00:30:00  \n",
       "4                     8.6754      4 2000-01-01 00:40:00  \n",
       "\n",
       "[5 rows x 28 columns]"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import featuretools as ft\n",
    "import utils\n",
    "\n",
    "data_path = 'data/train_FD004.txt'\n",
    "data = utils.load_data(data_path)\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## NASA Run To Failure Dataset\n",
    "In this dataset we have 249 engines (`engine_no`) which are monitored over time (`time_in_cycles`). Each engine had `operational_settings` and `sensor_measurements` recorded for each cycle. The **Remaining Useful Life** (RUL) is the amount of cycles an engine has left before it needs maintenance.\n",
    "What makes this dataset special is that the engines run all the way until failure, giving us precise RUL information for every engine at every point in time.\n",
    "\n",
    "To train a model that will predict RUL, we can can simulate real predictions on by choosing a random point in the life of the engine and only using the data from before that point. We can create features with that restriction easily by using [cutoff_times](https://docs.featuretools.com/automated_feature_engineering/handling_time.html) in Featuretools.\n",
    "\n",
    "The function `make_cutoff_times` in [utils](utils.py) does that sampling for both the `cutoff_time` and the label. You can run the next cell several times and see differing results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>engine_no</th>\n",
       "      <th>cutoff_time</th>\n",
       "      <th>RUL</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>index</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>2000-01-03 00:00:00</td>\n",
       "      <td>32</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2</td>\n",
       "      <td>2000-01-03 13:50:00</td>\n",
       "      <td>248</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3</td>\n",
       "      <td>2000-01-06 06:40:00</td>\n",
       "      <td>166</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>4</td>\n",
       "      <td>2000-01-08 01:30:00</td>\n",
       "      <td>183</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>5</td>\n",
       "      <td>2000-01-10 15:10:00</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       engine_no         cutoff_time  RUL\n",
       "index                                    \n",
       "1              1 2000-01-03 00:00:00   32\n",
       "2              2 2000-01-03 13:50:00  248\n",
       "3              3 2000-01-06 06:40:00  166\n",
       "4              4 2000-01-08 01:30:00  183\n",
       "5              5 2000-01-10 15:10:00    6"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cutoff_times = utils.make_cutoff_times(data)\n",
    "\n",
    "cutoff_times.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's walk through a row of the `cutoff_times` dataframe. In the third row, we have engine number 3. At 3:20 on January 6, the remaining useful life of engine number 3 is 213. Having a dataframe in this format tells Featuretools that the feature vector for engine number 3 should only be calculated with data from before that point in time. \n",
    "\n",
    "To apply Deep Feature Synthesis we need to establish an `EntitySet` structure for our data. The key insight in this step is that we're really interested in our data as collected by `engine`. We can create an `engines` entity by normalizing by the `engine_no` column in the raw data. In the next section, we'll create a feature matrix for the `engines` entity directly rather than the base dataframe of `recordings`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Entityset: Dataset\n",
       "  Entities:\n",
       "    recordings [Rows: 61249, Columns: 28]\n",
       "    engines [Rows: 249, Columns: 2]\n",
       "    cycles [Rows: 543, Columns: 2]\n",
       "  Relationships:\n",
       "    recordings.engine_no -> engines.engine_no\n",
       "    recordings.time_in_cycles -> cycles.time_in_cycles"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def make_entityset(data):\n",
    "    es = ft.EntitySet('Dataset')\n",
    "    es.entity_from_dataframe(dataframe=data,\n",
    "                             entity_id='recordings',\n",
    "                             index='index',\n",
    "                             time_index='time')\n",
    "\n",
    "    es.normalize_entity(base_entity_id='recordings', \n",
    "                        new_entity_id='engines',\n",
    "                        index='engine_no')\n",
    "\n",
    "    es.normalize_entity(base_entity_id='recordings', \n",
    "                        new_entity_id='cycles',\n",
    "                        index='time_in_cycles')\n",
    "    return es\n",
    "es = make_entityset(data)\n",
    "es"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualize EntitySet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n",
       " -->\n",
       "<!-- Title: Dataset Pages: 1 -->\n",
       "<svg width=\"556pt\" height=\"558pt\"\n",
       " viewBox=\"0.00 0.00 556.00 558.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 554)\">\n",
       "<title>Dataset</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-554 552,-554 552,4 -4,4\"/>\n",
       "<!-- recordings -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>recordings</title>\n",
       "<polygon fill=\"none\" stroke=\"#000000\" points=\"167.5,-98.5 167.5,-549.5 379.5,-549.5 379.5,-98.5 167.5,-98.5\"/>\n",
       "<text text-anchor=\"middle\" x=\"273.5\" y=\"-534.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">recordings</text>\n",
       "<polyline fill=\"none\" stroke=\"#000000\" points=\"167.5,-526.5 379.5,-526.5 \"/>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-511.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">index : index</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-496.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">engine_no : id</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-481.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">time_in_cycles : id</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-466.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">operational_setting_1 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-451.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">operational_setting_2 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-436.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">operational_setting_3 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-421.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_1 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-406.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_2 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-391.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_3 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-376.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_4 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-361.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_5 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-346.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_6 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-331.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_7 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-316.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_8 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-301.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_9 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-286.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_10 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-271.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_11 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-256.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_12 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-241.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_13 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-226.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_14 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-211.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_15 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-196.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_16 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-181.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_17 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-166.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_18 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-151.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_19 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-136.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_20 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-121.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">sensor_measurement_21 : numeric</text>\n",
       "<text text-anchor=\"start\" x=\"175.5\" y=\"-106.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">time : datetime_time_index</text>\n",
       "</g>\n",
       "<!-- engines -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>engines</title>\n",
       "<polygon fill=\"none\" stroke=\"#000000\" points=\"0,-.5 0,-61.5 265,-61.5 265,-.5 0,-.5\"/>\n",
       "<text text-anchor=\"middle\" x=\"132.5\" y=\"-46.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">engines</text>\n",
       "<polyline fill=\"none\" stroke=\"#000000\" points=\"0,-38.5 265,-38.5 \"/>\n",
       "<text text-anchor=\"start\" x=\"8\" y=\"-23.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">engine_no : index</text>\n",
       "<text text-anchor=\"start\" x=\"8\" y=\"-8.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">first_recordings_time : datetime_time_index</text>\n",
       "</g>\n",
       "<!-- recordings&#45;&gt;engines -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>recordings&#45;&gt;engines</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M216.25,-98.2201C216.25,-98.2201 216.25,-71.5162 216.25,-71.5162\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"219.7501,-71.5162 216.25,-61.5162 212.7501,-71.5163 219.7501,-71.5162\"/>\n",
       "<text text-anchor=\"middle\" x=\"186.75\" y=\"-73.6682\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">engine_no</text>\n",
       "</g>\n",
       "<!-- cycles -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>cycles</title>\n",
       "<polygon fill=\"none\" stroke=\"#000000\" points=\"283,-.5 283,-61.5 548,-61.5 548,-.5 283,-.5\"/>\n",
       "<text text-anchor=\"middle\" x=\"415.5\" y=\"-46.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">cycles</text>\n",
       "<polyline fill=\"none\" stroke=\"#000000\" points=\"283,-38.5 548,-38.5 \"/>\n",
       "<text text-anchor=\"start\" x=\"291\" y=\"-23.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">time_in_cycles : index</text>\n",
       "<text text-anchor=\"start\" x=\"291\" y=\"-8.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">first_recordings_time : datetime_time_index</text>\n",
       "</g>\n",
       "<!-- recordings&#45;&gt;cycles -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>recordings&#45;&gt;cycles</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M331.25,-98.2201C331.25,-98.2201 331.25,-71.5162 331.25,-71.5162\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"334.7501,-71.5162 331.25,-61.5162 327.7501,-71.5163 334.7501,-71.5162\"/>\n",
       "<text text-anchor=\"middle\" x=\"288.75\" y=\"-73.6682\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">time_in_cycles</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.dot.Digraph at 0xa251c4d30>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "es.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Step 2: DFS and Creating a Model\n",
    "With the work from the last section in hand, we can quickly build features using Deep Feature Synthesis (DFS). The function `ft.dfs` takes an `EntitySet` and stacks primitives like `Max`, `Min` and `Last` exhaustively across entities. Feel free to try the next step with a different primitive set to see how the results differ!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Built 290 features\n",
      "Elapsed: 04:23 | Remaining: 00:00 | Progress: 100%|██████████| Calculated: 11/11 chunks\n"
     ]
    }
   ],
   "source": [
    "fm, features = ft.dfs(entityset=es, \n",
    "                      target_entity='engines',\n",
    "                      agg_primitives=['last', 'max', 'min'],\n",
    "                      trans_primitives=[],\n",
    "                      cutoff_time=cutoff_times,\n",
    "                      max_depth=3,\n",
    "                      verbose=True)\n",
    "fm.to_csv('simple_fm.csv')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Machine Learning Baselines\n",
    "Before we use that feature matrix to make predictions, we should check how well guessing does on this dataset. We can use a `train_test_split` from scikit-learn to split our training data once and for all. Then, we'll check the following baselines:\n",
    "1. Always predict the median value of `y_train`\n",
    "2. Always predict the RUL as if every engine has the median lifespan in `X_train`\n",
    "\n",
    "We'll check those predictions by finding the mean of the absolute value of the errors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Baseline by median label: Mean Abs Error = 67.45\n"
     ]
    }
   ],
   "source": [
    "from sklearn.ensemble import RandomForestRegressor\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import mean_absolute_error\n",
    "\n",
    "fm = pd.read_csv('simple_fm.csv', index_col='engine_no')\n",
    "X = fm.copy().fillna(0)\n",
    "y = X.pop('RUL')\n",
    "\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=17)\n",
    "\n",
    "medianpredict1 = [np.median(y_train) for _ in y_test]\n",
    "print('Baseline by median label: Mean Abs Error = {:.2f}'.format(\n",
    "    mean_absolute_error(medianpredict1, y_test)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Baseline by median life: Mean Abs Error = 75.81\n"
     ]
    }
   ],
   "source": [
    "recordings_from_train = es['recordings'].df[es['recordings'].df['engine_no'].isin(y_train.index)]\n",
    "median_life = np.median(recordings_from_train.groupby(['engine_no']).apply(lambda df: df.shape[0]))\n",
    "\n",
    "recordings_from_test = es['recordings'].df[es['recordings'].df['engine_no'].isin(y_test.index)]\n",
    "life_in_test = recordings_from_test.groupby(['engine_no']).apply(lambda df: df.shape[0])-y_test\n",
    "\n",
    "medianpredict2 = (median_life - life_in_test).apply(lambda row: max(row, 0))\n",
    "print('Baseline by median life: Mean Abs Error = {:.2f}'.format(\n",
    "    mean_absolute_error(medianpredict2, y_test)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Step 3: Using the Model\n",
    "Now, we can use our created features to fit a `RandomForestRegressor` to our data and see if we can improve on the previous scores."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Mean Abs Error: 37.26\n",
      "1: MAX(recordings.cycles.LAST(recordings.sensor_measurement_11)) [0.093]\n",
      "2: MAX(recordings.sensor_measurement_11) [0.090]\n",
      "3: MAX(recordings.cycles.LAST(recordings.sensor_measurement_17)) [0.088]\n",
      "4: MAX(recordings.sensor_measurement_17) [0.075]\n",
      "5: MAX(recordings.sensor_measurement_4) [0.065]\n",
      "6: MAX(recordings.cycles.LAST(recordings.sensor_measurement_2)) [0.053]\n",
      "7: MAX(recordings.cycles.LAST(recordings.sensor_measurement_4)) [0.041]\n",
      "8: MAX(recordings.sensor_measurement_2) [0.037]\n",
      "9: MAX(recordings.sensor_measurement_13) [0.031]\n",
      "10: MAX(recordings.cycles.LAST(recordings.sensor_measurement_13)) [0.023]\n",
      "-----\n",
      "\n"
     ]
    }
   ],
   "source": [
    "reg = RandomForestRegressor(n_estimators=100)\n",
    "reg.fit(X_train, y_train)\n",
    "    \n",
    "preds = reg.predict(X_test)\n",
    "scores = mean_absolute_error(preds, y_test)\n",
    "print('Mean Abs Error: {:.2f}'.format(scores))\n",
    "high_imp_feats = utils.feature_importances(X, reg, feats=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we can apply the exact same transformations (including DFS) to our test data. For this particular case, the real answer isn't in the data so we don't need to worry about cutoff times."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded data with:\n",
      "41214 Recordings\n",
      "248 Engines\n",
      "21 Sensor Measurements\n",
      "3 Operational Settings\n",
      "Elapsed: 00:47 | Remaining: 00:00 | Progress: 100%|██████████| Calculated: 11/11 chunks\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>LAST(recordings.time_in_cycles)</th>\n",
       "      <th>LAST(recordings.operational_setting_1)</th>\n",
       "      <th>LAST(recordings.operational_setting_2)</th>\n",
       "      <th>LAST(recordings.operational_setting_3)</th>\n",
       "      <th>LAST(recordings.sensor_measurement_1)</th>\n",
       "      <th>LAST(recordings.sensor_measurement_2)</th>\n",
       "      <th>LAST(recordings.sensor_measurement_3)</th>\n",
       "      <th>LAST(recordings.sensor_measurement_4)</th>\n",
       "      <th>LAST(recordings.sensor_measurement_5)</th>\n",
       "      <th>LAST(recordings.sensor_measurement_6)</th>\n",
       "      <th>...</th>\n",
       "      <th>MIN(recordings.cycles.MIN(recordings.sensor_measurement_12))</th>\n",
       "      <th>MIN(recordings.cycles.MIN(recordings.sensor_measurement_13))</th>\n",
       "      <th>MIN(recordings.cycles.MIN(recordings.sensor_measurement_14))</th>\n",
       "      <th>MIN(recordings.cycles.MIN(recordings.sensor_measurement_15))</th>\n",
       "      <th>MIN(recordings.cycles.MIN(recordings.sensor_measurement_16))</th>\n",
       "      <th>MIN(recordings.cycles.MIN(recordings.sensor_measurement_17))</th>\n",
       "      <th>MIN(recordings.cycles.MIN(recordings.sensor_measurement_18))</th>\n",
       "      <th>MIN(recordings.cycles.MIN(recordings.sensor_measurement_19))</th>\n",
       "      <th>MIN(recordings.cycles.MIN(recordings.sensor_measurement_20))</th>\n",
       "      <th>MIN(recordings.cycles.MIN(recordings.sensor_measurement_21))</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>engine_no</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>230</td>\n",
       "      <td>25.0070</td>\n",
       "      <td>0.6214</td>\n",
       "      <td>60.0</td>\n",
       "      <td>462.54</td>\n",
       "      <td>537.66</td>\n",
       "      <td>1264.31</td>\n",
       "      <td>1046.41</td>\n",
       "      <td>7.05</td>\n",
       "      <td>8.99</td>\n",
       "      <td>...</td>\n",
       "      <td>128.26</td>\n",
       "      <td>2027.74</td>\n",
       "      <td>7849.80</td>\n",
       "      <td>8.2040</td>\n",
       "      <td>0.02</td>\n",
       "      <td>302</td>\n",
       "      <td>1915</td>\n",
       "      <td>84.93</td>\n",
       "      <td>10.19</td>\n",
       "      <td>6.1453</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>153</td>\n",
       "      <td>41.9989</td>\n",
       "      <td>0.8400</td>\n",
       "      <td>100.0</td>\n",
       "      <td>445.00</td>\n",
       "      <td>549.96</td>\n",
       "      <td>1354.05</td>\n",
       "      <td>1133.55</td>\n",
       "      <td>3.91</td>\n",
       "      <td>5.72</td>\n",
       "      <td>...</td>\n",
       "      <td>128.26</td>\n",
       "      <td>2027.74</td>\n",
       "      <td>7849.80</td>\n",
       "      <td>8.2899</td>\n",
       "      <td>0.02</td>\n",
       "      <td>302</td>\n",
       "      <td>1915</td>\n",
       "      <td>84.93</td>\n",
       "      <td>10.19</td>\n",
       "      <td>6.1453</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>141</td>\n",
       "      <td>42.0005</td>\n",
       "      <td>0.8401</td>\n",
       "      <td>100.0</td>\n",
       "      <td>445.00</td>\n",
       "      <td>549.47</td>\n",
       "      <td>1341.06</td>\n",
       "      <td>1118.90</td>\n",
       "      <td>3.91</td>\n",
       "      <td>5.69</td>\n",
       "      <td>...</td>\n",
       "      <td>128.26</td>\n",
       "      <td>2027.74</td>\n",
       "      <td>7849.80</td>\n",
       "      <td>8.2998</td>\n",
       "      <td>0.02</td>\n",
       "      <td>302</td>\n",
       "      <td>1915</td>\n",
       "      <td>84.93</td>\n",
       "      <td>10.19</td>\n",
       "      <td>6.1453</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>208</td>\n",
       "      <td>25.0018</td>\n",
       "      <td>0.6207</td>\n",
       "      <td>60.0</td>\n",
       "      <td>462.54</td>\n",
       "      <td>536.06</td>\n",
       "      <td>1253.49</td>\n",
       "      <td>1038.53</td>\n",
       "      <td>7.05</td>\n",
       "      <td>9.00</td>\n",
       "      <td>...</td>\n",
       "      <td>128.26</td>\n",
       "      <td>2027.74</td>\n",
       "      <td>7849.80</td>\n",
       "      <td>8.2107</td>\n",
       "      <td>0.02</td>\n",
       "      <td>302</td>\n",
       "      <td>1915</td>\n",
       "      <td>84.93</td>\n",
       "      <td>10.19</td>\n",
       "      <td>6.1453</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>51</td>\n",
       "      <td>25.0039</td>\n",
       "      <td>0.6200</td>\n",
       "      <td>60.0</td>\n",
       "      <td>462.54</td>\n",
       "      <td>537.36</td>\n",
       "      <td>1263.60</td>\n",
       "      <td>1052.52</td>\n",
       "      <td>7.05</td>\n",
       "      <td>9.03</td>\n",
       "      <td>...</td>\n",
       "      <td>128.73</td>\n",
       "      <td>2027.93</td>\n",
       "      <td>7856.49</td>\n",
       "      <td>8.3038</td>\n",
       "      <td>0.02</td>\n",
       "      <td>302</td>\n",
       "      <td>1915</td>\n",
       "      <td>84.93</td>\n",
       "      <td>10.19</td>\n",
       "      <td>6.1453</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 290 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "           LAST(recordings.time_in_cycles)  \\\n",
       "engine_no                                    \n",
       "1                                      230   \n",
       "2                                      153   \n",
       "3                                      141   \n",
       "4                                      208   \n",
       "5                                       51   \n",
       "\n",
       "           LAST(recordings.operational_setting_1)  \\\n",
       "engine_no                                           \n",
       "1                                         25.0070   \n",
       "2                                         41.9989   \n",
       "3                                         42.0005   \n",
       "4                                         25.0018   \n",
       "5                                         25.0039   \n",
       "\n",
       "           LAST(recordings.operational_setting_2)  \\\n",
       "engine_no                                           \n",
       "1                                          0.6214   \n",
       "2                                          0.8400   \n",
       "3                                          0.8401   \n",
       "4                                          0.6207   \n",
       "5                                          0.6200   \n",
       "\n",
       "           LAST(recordings.operational_setting_3)  \\\n",
       "engine_no                                           \n",
       "1                                            60.0   \n",
       "2                                           100.0   \n",
       "3                                           100.0   \n",
       "4                                            60.0   \n",
       "5                                            60.0   \n",
       "\n",
       "           LAST(recordings.sensor_measurement_1)  \\\n",
       "engine_no                                          \n",
       "1                                         462.54   \n",
       "2                                         445.00   \n",
       "3                                         445.00   \n",
       "4                                         462.54   \n",
       "5                                         462.54   \n",
       "\n",
       "           LAST(recordings.sensor_measurement_2)  \\\n",
       "engine_no                                          \n",
       "1                                         537.66   \n",
       "2                                         549.96   \n",
       "3                                         549.47   \n",
       "4                                         536.06   \n",
       "5                                         537.36   \n",
       "\n",
       "           LAST(recordings.sensor_measurement_3)  \\\n",
       "engine_no                                          \n",
       "1                                        1264.31   \n",
       "2                                        1354.05   \n",
       "3                                        1341.06   \n",
       "4                                        1253.49   \n",
       "5                                        1263.60   \n",
       "\n",
       "           LAST(recordings.sensor_measurement_4)  \\\n",
       "engine_no                                          \n",
       "1                                        1046.41   \n",
       "2                                        1133.55   \n",
       "3                                        1118.90   \n",
       "4                                        1038.53   \n",
       "5                                        1052.52   \n",
       "\n",
       "           LAST(recordings.sensor_measurement_5)  \\\n",
       "engine_no                                          \n",
       "1                                           7.05   \n",
       "2                                           3.91   \n",
       "3                                           3.91   \n",
       "4                                           7.05   \n",
       "5                                           7.05   \n",
       "\n",
       "           LAST(recordings.sensor_measurement_6)  \\\n",
       "engine_no                                          \n",
       "1                                           8.99   \n",
       "2                                           5.72   \n",
       "3                                           5.69   \n",
       "4                                           9.00   \n",
       "5                                           9.03   \n",
       "\n",
       "                                       ...                               \\\n",
       "engine_no                              ...                                \n",
       "1                                      ...                                \n",
       "2                                      ...                                \n",
       "3                                      ...                                \n",
       "4                                      ...                                \n",
       "5                                      ...                                \n",
       "\n",
       "           MIN(recordings.cycles.MIN(recordings.sensor_measurement_12))  \\\n",
       "engine_no                                                                 \n",
       "1                                                     128.26              \n",
       "2                                                     128.26              \n",
       "3                                                     128.26              \n",
       "4                                                     128.26              \n",
       "5                                                     128.73              \n",
       "\n",
       "           MIN(recordings.cycles.MIN(recordings.sensor_measurement_13))  \\\n",
       "engine_no                                                                 \n",
       "1                                                    2027.74              \n",
       "2                                                    2027.74              \n",
       "3                                                    2027.74              \n",
       "4                                                    2027.74              \n",
       "5                                                    2027.93              \n",
       "\n",
       "           MIN(recordings.cycles.MIN(recordings.sensor_measurement_14))  \\\n",
       "engine_no                                                                 \n",
       "1                                                    7849.80              \n",
       "2                                                    7849.80              \n",
       "3                                                    7849.80              \n",
       "4                                                    7849.80              \n",
       "5                                                    7856.49              \n",
       "\n",
       "           MIN(recordings.cycles.MIN(recordings.sensor_measurement_15))  \\\n",
       "engine_no                                                                 \n",
       "1                                                     8.2040              \n",
       "2                                                     8.2899              \n",
       "3                                                     8.2998              \n",
       "4                                                     8.2107              \n",
       "5                                                     8.3038              \n",
       "\n",
       "           MIN(recordings.cycles.MIN(recordings.sensor_measurement_16))  \\\n",
       "engine_no                                                                 \n",
       "1                                                       0.02              \n",
       "2                                                       0.02              \n",
       "3                                                       0.02              \n",
       "4                                                       0.02              \n",
       "5                                                       0.02              \n",
       "\n",
       "           MIN(recordings.cycles.MIN(recordings.sensor_measurement_17))  \\\n",
       "engine_no                                                                 \n",
       "1                                                        302              \n",
       "2                                                        302              \n",
       "3                                                        302              \n",
       "4                                                        302              \n",
       "5                                                        302              \n",
       "\n",
       "           MIN(recordings.cycles.MIN(recordings.sensor_measurement_18))  \\\n",
       "engine_no                                                                 \n",
       "1                                                       1915              \n",
       "2                                                       1915              \n",
       "3                                                       1915              \n",
       "4                                                       1915              \n",
       "5                                                       1915              \n",
       "\n",
       "           MIN(recordings.cycles.MIN(recordings.sensor_measurement_19))  \\\n",
       "engine_no                                                                 \n",
       "1                                                      84.93              \n",
       "2                                                      84.93              \n",
       "3                                                      84.93              \n",
       "4                                                      84.93              \n",
       "5                                                      84.93              \n",
       "\n",
       "           MIN(recordings.cycles.MIN(recordings.sensor_measurement_20))  \\\n",
       "engine_no                                                                 \n",
       "1                                                      10.19              \n",
       "2                                                      10.19              \n",
       "3                                                      10.19              \n",
       "4                                                      10.19              \n",
       "5                                                      10.19              \n",
       "\n",
       "           MIN(recordings.cycles.MIN(recordings.sensor_measurement_21))  \n",
       "engine_no                                                                \n",
       "1                                                     6.1453             \n",
       "2                                                     6.1453             \n",
       "3                                                     6.1453             \n",
       "4                                                     6.1453             \n",
       "5                                                     6.1453             \n",
       "\n",
       "[5 rows x 290 columns]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data2 = utils.load_data('data/test_FD004.txt')\n",
    "es2 = make_entityset(data2)\n",
    "fm2 = ft.calculate_feature_matrix(entityset=es2, features=features, verbose=True)\n",
    "fm2.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Mean Abs Error: 44.28\n",
      "Baseline by median label: Mean Abs Error = 50.55\n",
      "Baseline by median life: Mean Abs Error = 50.29\n"
     ]
    }
   ],
   "source": [
    "X = fm2.copy().fillna(0)\n",
    "y = pd.read_csv('data/RUL_FD004.txt', sep=' ', header=-1, names=['RUL'], index_col=False)\n",
    "preds2 = reg.predict(X)\n",
    "print('Mean Abs Error: {:.2f}'.format(mean_absolute_error(preds2, y)))\n",
    "\n",
    "medianpredict1 = [np.median(y_train) for _ in preds2]\n",
    "print('Baseline by median label: Mean Abs Error = {:.2f}'.format(\n",
    "    mean_absolute_error(medianpredict1, y)))\n",
    "\n",
    "medianpredict2 = (median_life - es2['recordings'].df.groupby(['engine_no']).apply(lambda df: df.shape[0])).apply(lambda row: max(row, 0))\n",
    "print('Baseline by median life: Mean Abs Error = {:.2f}'.format(\n",
    "    mean_absolute_error(medianpredict2, y)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# This is the simple version of a more advanced notebook that can be found in the [second](Advanced%20Featuretools%20RUL.ipynb) notebook. That notebook will show how to use a novel entityset structure, custom primitives, and automated hyperparameter tuning to improve the score."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Save output files\n",
    "\n",
    "import os\n",
    "\n",
    "try:\n",
    "    os.mkdir(\"output\")\n",
    "except:\n",
    "    pass\n",
    "\n",
    "fm.to_csv('output/simple_train_feature_matrix.csv')\n",
    "cutoff_times.to_csv('output/simple_train_label_times.csv')\n",
    "fm2.to_csv('output/simple_test_feature_matrix.csv')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p>\n",
    "    <img src=\"https://www.featurelabs.com/wp-content/uploads/2017/12/logo.png\" alt=\"Featuretools\" />\n",
    "</p>\n",
    "\n",
    "Featuretools was created by the developers at [Feature Labs](https://www.featurelabs.com/). If building impactful data science pipelines is important to you or your business, please [get in touch](https://www.featurelabs.com/contact)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
